package com.fingard.dsp.bank.directbank.czb01;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptData;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptDataHelper;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directConfig.ReceiptProConfig;
import com.fingard.dsp.bank.directbank.bankInterface.IReceiptPro;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.ReqQryReceipt;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.RetAtsReceipt;
import com.fingard.dsp.bank.reqrespobj.transaction.Req7516HisTrans;
import com.fingard.dsp.bank.reqrespobj.transaction.detail.RetAtsTransDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.text.StringHelper;
import com.fingard.util.SmbFileUtil;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import sun.misc.BASE64Decoder;

import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class CZB01ReceiptPro extends CZB01Base implements IReceiptPro {

    private ReceiptData rcpt = new ReceiptData();

    /**
     * （200120）回单接口，在调用接口前，先调用一次200112明细查询接口，
     * 并在（200120）接口需要上传200112明细接口中返回的流水号serial_no 字段
     * 2、DSP回传ATS明细、回单数据时候将serial_no 字段传值到BANKSERIALNUMBER字段
     * 3、DSP回传ATS回单数据将回单查询时上传的serial_no 字段传值到BANKSERIALNUMBER字段
     *
     * @param pConfig
     * @param pReqReceipt
     * @param pOneDay
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsReceipt qryReceiptOneDay(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay) throws Exception {
        String qryDay8 = Format.Date8Format.format(pOneDay);
        //清除前一次查询的retAtsTransDetails对象中的内容
        super.retRetailList = new ArrayList();
        //1.调用200112接口查回明细数据
        List<RetAtsTransDetail> retAtsTransDetails = getTransDetail(pReqReceipt, qryDay8);
        if (retAtsTransDetails == null || retAtsTransDetails.size() == 0) {
            WriteBankLogLn("日期" + qryDay8 + "查询到的明细为空，不查询回单信息");
            return null;
        }
        String queryType = StringHelper.isNullOrEmpty(getBankConfig().getValueAsString("200120queryTypeByPayReqNo")) ? "1" : getBankConfig().getValueAsString("200120queryTypeByPayReqNo");
        WriteBankLogLn("200120接口查询模式为：" + ("1".equals(queryType) ? "银行流水号查询" : "付款请求号查询"));
        String receiptDownType = getBankConfig().getValueAsString("receiptDownType");
        WriteBankLogLn("回单下载到DSP的模式为：" + receiptDownType);
        ReceiptDataHelper receiptHelper = new ReceiptDataHelper(pReqReceipt.reqHeader.tenant, pOneDay);//回单数据保存类，分区分表
        //2.调用200120接口查回回单，一次查询一张回单
        for (int i = 0; i < retAtsTransDetails.size(); i++) {
            String localpath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, Format.Date8Format.parse(qryDay8)) + File.separator + pReqReceipt.actNum + File.separator + qryDay8;
            if (FileHelper.existFile(localpath + retAtsTransDetails.get(i).bnkSeqNo + ".pdf")) {
                WriteBankLogLn("文件名为：" + retAtsTransDetails.get(i).bnkSeqNo + ".pdf" + "的文件已经下载过，如需重新下载，请手动删除" + localpath + "目录下的该文件后重新查询！");
                continue;
            }
            singleReceiptQueryBy200120(pReqReceipt, pConfig, qryDay8, retAtsTransDetails.get(i), queryType, receiptDownType, receiptHelper);
        }
//        String tempPath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) + File.separator + qryDay8;
//        List<String> list = receiptHelper.getIstNbrList(pReqReceipt.actNum, pOneDay);
//        WriteBankLogLn(pReqReceipt.actNum + "，" + qryDay8 + "需要进行下载的回单文件个数：" + list.size());
//        if (list.size() <= 0) {
//            return null;
//        }
//        File fileDir = new File(tempPath);
//        int[] retVals = getPdfLoop(pConfig, pReqReceipt, pOneDay, receiptHelper, fileDir, list);
//        //[0]总数 [1]新增 [2]已存在
//        WriteBankLogLn("目录" + fileDir + "\r\n遍历总数" + retVals[0] + "，新增" + retVals[1] + "条，已存在" + (retVals[0] - retVals[1]) + "条");
        return null;
    }

    /**
     * 公共方法，提取pdf文件，农行是所有账号的回单一起提供，遍历所有pdf
     * [0]总数 [1]新增 [2]已存在
     *
     * @param pConfig
     * @param pReqReceipt
     * @param pOneDay
     * @param pReceiptHelper
     * @param pDir
     * @param dataList
     * @return
     */
    private int[] getPdfLoop(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay, ReceiptDataHelper pReceiptHelper, File pDir, List<String> dataList) {
        String qryDay8 = Format.Date8Format.format(pOneDay);
        int[] retVals = new int[2];
        retVals[0] = 0;//总pdf个数
        retVals[1] = 0;//新增
        File[] files = pDir.listFiles();
        for (File eachFile : files) {
            try {
                if (eachFile.isDirectory()) {
                    int[] subVals = getPdfLoop(pConfig, pReqReceipt, pOneDay, pReceiptHelper, eachFile, dataList);
                    retVals[0] = retVals[0] + subVals[0];
                    retVals[1] = retVals[1] + subVals[1];
                }
                String[] nameAndExt = StringHelper.splitFileNameAndExt(eachFile.getName());
                if ("pdf".equalsIgnoreCase(nameAndExt[1])) {
                    retVals[0] = retVals[0] + 1;
                    //交易日期_核心流水_子顺序号_查询账号_金额
                    //20200108_1018111_1_200203040000000579_0.01.pdf
                    String[] nameSp = nameAndExt[0].split("_");
                    if (nameSp.length != 5) {
                        WriteBankLogLn("回单文件:" + eachFile.getName() + "文件名格式不符合预期");
                        continue;
                    }
                    for (String istNbr : dataList) {
                        if (istNbr.equals(nameSp[0] + nameSp[1] + nameSp[2])) {
                            //重命名
                            String renameToPath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) + File.separator + qryDay8 + File.separator + pReqReceipt.actNum;
                            FileHelper.mkdirsIfNotExists(renameToPath);
                            renameToPath += File.separator + eachFile.getName();
                            File destFile = new File(renameToPath);
                            boolean reResult;
                            if (destFile.exists()) {
                                reResult = true;
                            } else {
                                reResult = eachFile.renameTo(destFile);
                            }
                            if (reResult) {
                                //数据库中存储的路径是相对pConfig.localSaveMainDir的相对路径
                                String relativePath = StringHelper.getRelativePath(destFile.getAbsolutePath(), pConfig.localSaveMainDir);
                                int inRe = pReceiptHelper.updateDownState(pReqReceipt.actNum, istNbr, relativePath, eachFile.getName(), "2");
                                if (inRe > 0) {
                                    retVals[1] = retVals[1] + 1;
                                }
                                WriteBankLogLn("回单编号" + istNbr + "，文件" + nameSp[1] + "下载成功，重命名成功，更新影响行数：" + inRe);
                            } else {
                                WriteBankLogLn("回单编号" + istNbr + "重命名失败：\r\n" + eachFile.getAbsolutePath() + "\r\n重命名为：\r\n" + renameToPath);
                            }
                            break;
                        }
                    }
                }
            } catch (Exception ex) {
                WriteBankLogLn(ex, eachFile.getAbsolutePath());
            }
        }
        return retVals;
    }

    /**
     * Step2
     * 调用200120单笔交易回单查询接口
     *
     * @param queryType
     * @param pReqReceipt
     * @param pConfig
     * @param detail
     * @param queryType
     * @param receiptHelper
     */
    private void singleReceiptQueryBy200120(ReqQryReceipt pReqReceipt, ReceiptProConfig pConfig, String qryDay8, RetAtsTransDetail detail, String receiptDownType, String queryType, ReceiptDataHelper receiptHelper) {
        try {
            CZB01Header bankHeader = new CZB01Header();
            bankHeader.transCode = "200120";
            bankHeader.reqSeqNo = pReqReceipt.reqHeader.transSeqID;
            XmlTextWriter xmlWriter = new XmlTextWriter();
            writeCommonHeader(xmlWriter, bankHeader);

            xmlWriter.writeStartElement("body");

            xmlWriter.writeElementString("query_type", StringHelper.isNullOrEmpty(getBankConfig().getValueAsString("200120queryTypeByPayReqNo")) ? "1" : getBankConfig().getValueAsString("200120queryTypeByPayReqNo"));
            xmlWriter.writeElementString("accno", pReqReceipt.actNum);
            xmlWriter.writeElementString("date", qryDay8);
            xmlWriter.writeElementString("serial_no", detail.originator.trim());
            xmlWriter.writeElementString("req_no", "");
            xmlWriter.writeEndDocument();
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
//            String[] tmpStrRet = new String[]{"", "<ap>\n" +
//                    "    <head>\n" +
//                    "        <tr_code>200112</tr_code>\n" +
//                    "        <cms_corp_no></cms_corp_no>\n" +
//                    "        <user_no></user_no>\n" +
//                    "        <req_no>1238536714</req_no>\n" +
//                    "        <serial_no>13174018</serial_no>\n" +
//                    "        <tr_acdt>20200430</tr_acdt>\n" +
//                    "        <tr_time>124122</tr_time>\n" +
//                    "        <succ_flag>0</succ_flag>\n" +
//                    "        <ret_info>交易成功</ret_info>\n" +
//                    "        <ret_code>0000</ret_code>\n" +
//                    "        <ext_info></ext_info>\n" +
//                    "        <reserved></reserved>\n" +
//                    "        <file_flag>1</file_flag>\n" +
//                    "        <org_code></org_code>\n" +
//                    "    </head>\n" +
//                    "    <body>\n" +
//                    "        <file_name>20200108_202017_2_200203040000000579_10000000.00.pdf</file_name>\n" +
//                    "        <record_num>1</record_num>\n" +
//                    "        <total_record_num>1</total_record_num>\n" +
//                    "        <field_num>23</field_num>\n" +
//                    "    </body>\n" +
//                    "</ap>"};

            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/ap/head/ret_code");
                    String retInfo = tmpBkReader.getFirstText("/ap/head/ret_info");
                    if (tmpRetCode.equals("0000")) {
                        String fileFlag = tmpBkReader.getFirstText("/ap/head/file_flag");
                        if ("1".equals(fileFlag)) {
                            String fileName = tmpBkReader.getFirstText("/ap/body/file_name");
                            WriteBankLogLn("日期为" + qryDay8 + "，流水号为" + detail.originator + "回单查询成功，文件名为：" + fileName);
                            //将回单文件下载到DSP本地目录
                            downloadReceiptToLocalDir(pConfig, fileName, pReqReceipt, qryDay8, detail, receiptDownType, receiptHelper);
                        } else {
                            WriteBankLogLn("日期为" + qryDay8 + "，流水号为" + detail.originator + "\r\n" + "查询时银行没有返回回单文件");
                        }
                    } else {
                        WriteBankLogLn("日期为" + qryDay8 + "，流水号为" + detail.originator + "\r\n" + "查询时银行返回错误，错误信息为：" + retInfo);
                    }
                } else {
                    WriteBankLogLn("日期为" + qryDay8 + "，流水号为" + detail.originator + "\r\n" + "查询时银行返回错误，错误信息为：" + tmpSbMsg);
                }
            } else {
                WriteBankLogLn(tmpStrRet[1]);
            }
        } catch (Exception e) {
            WriteBankLogLn("日期为" + qryDay8 + "，流水号为" + detail.originator + "\r\n" + "查询时发生异常，异常信息为：" + e.getMessage());
        }
    }

    /**
     * Step3,将银行前置机回单文件下载到DSP
     *
     * @param pConfig
     * @param fileName
     * @param pReqReceipt
     * @param qryDay8
     * @param detail
     * @param receiptDownType
     * @param receiptHelper
     */
    private void downloadReceiptToLocalDir(ReceiptProConfig pConfig, String fileName, ReqQryReceipt pReqReceipt, String qryDay8, RetAtsTransDetail detail, String receiptDownType, ReceiptDataHelper receiptHelper) throws Exception {
        String localpath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, Format.Date8Format.parse(qryDay8)) + File.separator + pReqReceipt.actNum + File.separator + qryDay8;
        FileHelper.mkdirsIfNotExists(localpath);
        FileHelper.mkdirsIfNotExists(localpath);
        WriteBankLogLn("浙商银行下载文件：" + localpath + "，下载文件名：" + fileName);
        if ("sftp".equals(receiptDownType)) {
            //Sftp方式
            SftpPortClient sftpPortClient = null;

            try {
                FtpSet ftpSet = bankFront.getFtpSet("receipt");
                ftpSet.downDir = StringHelper.trimEnd(ftpSet.downDir, "/") + "/";
                WriteBankLogLn("SFTP下载地址" + ftpSet.serverIP + ":" + ftpSet.port);

                sftpPortClient = new SftpPortClient(ftpSet);
                WriteBankLogLn("下载到本地目录为：" + localpath);
                WriteBankLogLn("sftp目录下文件名为：" + fileName);
                FtpReceiver ftpReceiver = sftpPortClient.downloadFileByName("", localpath, fileName);
                if (ftpReceiver.isCompleted) {
                    WriteBankLogLn("下载成功，下载路径为：" + localpath + "文件名为" + fileName);
                } else {
                    WriteBankLogLn("下载失败，文件名为" + fileName);
                }
            } catch (Exception e) {
                e.printStackTrace();
                WriteBankLogLn(e);
            }
        } else if ("ftp".equals(receiptDownType)) {
            FtpSet ftpSet = bankFront.getFtpSet("receipt");
            FtpPortClient client = new FtpPortClient(ftpSet);
            FtpReceiver ftpReceiver = client.downloadFile(fileName, localpath);
            if (!ftpReceiver.isCompleted) {
                WriteBankLogLn(ftpReceiver.connMsg);
            } else if (ConnState.FAIL.equals(ftpReceiver.connState)) {
                WriteBankLogLn("下载失败");
            } else {
                WriteBankLogLn("下载成功");
            }
        } else {
            //共享目录方式
            if (StringHelper.hasAnyChar(bankFront.bkTransFolder)) {
                if (bankFront.bkTransFolder.startsWith("smb://")) {
                    StringBuilder smbSb = new StringBuilder();
                    SmbFileUtil.smbDownload(localpath, bankFront.bkTransFolder, fileName, smbSb);
                    WriteBankLogLn(fileName + "回单下载成功");
                } else {
                    String srcFilePath = StringHelper.trimEndFileSp(bankFront.bkTransFolder) + File.separator + fileName;
                    FileHelper.copyFile(srcFilePath, localpath + File.separator + fileName);
                }
            } else {
                throw new Exception("请配置银行前置机回单目录");
            }
        }
        //将回单信息保存到数据库
        saveReceiptInfoToDB(receiptHelper, localpath, detail, pConfig, qryDay8, fileName);
    }

    /**
     * Step4，将回单信息入库
     *
     * @param receiptHelper
     * @param localpath
     * @param detail
     * @param pConfig
     * @param qryDay8
     * @param fileName
     */
    private void saveReceiptInfoToDB(ReceiptDataHelper receiptHelper, String localpath, RetAtsTransDetail detail, ReceiptProConfig pConfig, String qryDay8, String fileName) throws Exception {
        rcpt.ownAct = detail.actNum;
        rcpt.bank = "31601";
        rcpt.srcSys = "CZB01";
        if (!StringHelper.isNullOrEmpty(detail.base64Str)) {
            byte[] bytes = new BASE64Decoder().decodeBuffer(detail.base64Str);
            String decode = new String(bytes, getCharset());
        }
        rcpt.istNbr = fileName.replace(".pdf", "");
        rcpt.receiptNo = rcpt.istNbr;
        rcpt.localFile = StringHelper.getRelativePath(localpath + File.separator + fileName, pConfig.localSaveMainDir);
        rcpt.setBusDate(Format.Date8Format.parse(qryDay8));
        rcpt.srcFile = fileName;
        rcpt.cur = detail.cur;
        rcpt.ownAct = detail.actNum;
        rcpt.bnkSeqNo = detail.originator.trim();
        rcpt.busRef = "";
        rcpt.downState = "2";
        rcpt.busDate = Integer.parseInt(qryDay8);
        rcpt.amount = new BigDecimal(detail.tranAmt);
        rcpt.voucherNo = "";
        int inRe = receiptHelper.insertIfNotExist(rcpt, true);
        WriteBankLogLn(rcpt.receiptNo + "写入数据库，影响行数：" + inRe);
    }

    /**
     * Step1
     * 调用历史明细查询接口查回明细数据
     *
     * @param pReqReceipt
     * @return
     * @throws Exception
     */
    private List<RetAtsTransDetail> getTransDetail(ReqQryReceipt pReqReceipt, String qryDay8) throws Exception {
        WriteBankLogLn("开始查询" + qryDay8 + "明细信息！");
        Req7516HisTrans p_req7516 = new Req7516HisTrans(pReqReceipt.reqHeader);
        p_req7516.dateFrom = qryDay8;
        p_req7516.dateTo = qryDay8;
        p_req7516.actNum = pReqReceipt.actNum;
        p_req7516.actCur = pReqReceipt.actCur;
        p_req7516.actArea = pReqReceipt.areaCode;
        hisTrans_200112(p_req7516);
        WriteBankLogLn(qryDay8 + "明细信息查询结束");
        return super.retRetailList;
    }
}
